package com.jade.editor.domain.ani;

import java.awt.Polygon;
import java.io.File;
import java.io.FileFilter;
import java.util.ArrayList;

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Region;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;

import com.jade.editor.domain.obj.ObjectModel;
import com.jade.editor.domain.parts.DrawArea;
import com.jade.editor.domain.parts.ISolve;

import org.eclipse.swt.widgets.ProgressBar;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;


public class PlacementMng extends Dialog {
	
	private String _aniName = "";
	private DrawArea _drawArea = null;
	private Anisotropy _ani = null;
	private ArrayList<ObjectModel> _olist = new ArrayList<ObjectModel>();
	private ArrayList<ObjectModel> _placedlist = new ArrayList<ObjectModel>();
	private Region _domain = null;
	private Point _size = null;
	private ISolve _plugAni = null;
	
	private ProgressBar _bar = null;
	private Button _btnRun = null;
	private Button _button = null;
	private File _pathFile = null;
	

	/**
	 * Create the dialog.
	 * @param parentShell
	 */
	public PlacementMng(Shell parentShell, DrawArea drawArea, File pathfile) {
		super(parentShell);
		_pathFile = pathfile;
		
		if (drawArea.getAnisotropy() != null){
			_drawArea = drawArea;
			_ani = drawArea.getAnisotropy();
			
			if(_ani.getAniType().equals(Anisotropy.ANI_DRAWABLE)){
				_aniName = new File(_ani.getAniModel().getAniPath()).getName();
			}
			else{
				_plugAni = _ani.getPlugAni();
			}
			Point size = _drawArea.getDrawAreaSize();
			_domain = new Region();
			int[] rg = {0,0, size.x,0, size.x,size.y, 0,size.y};
			_domain.add(rg);
			_size = _drawArea.getDrawAreaSize();
			}
		else{
			close();
		}
	}

	/**
	 * Create contents of the dialog.
	 * @param parent
	 */
	@Override
	protected Control createDialogArea(Composite parent) {
		final Composite container = (Composite) super.createDialogArea(parent);
		container.setLayout(null);
		
		_bar = new ProgressBar(container, SWT.NONE);
		_bar.setBounds(10, 10, 525, 46);
		
		_btnRun = new Button(container, SWT.NONE);
		_btnRun.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {
				
				if (_drawArea.getAnisotropy() != null){
					_button.setEnabled(false);
					
					if(_drawArea.getAnisotropy().getAniType().equals(Anisotropy.ANI_DRAWABLE)){
						_aniName = new File(_ani.getAniModel().getAniPath()).getName();
						initDataDrawable();
					}
					else if (_drawArea.getAnisotropy().getAniType().equals(Anisotropy.ANI_PLUGABLE)){
						_plugAni = _drawArea.getAnisotropy().getPlugAni();
						initDataPlugable();
					}
				}
				else{
					close();
				}
				
			}
		});
		_btnRun.setBounds(208, 77, 136, 46);
		_btnRun.setText("Run");
		
	

		
		return container;
	}

	/**
	 * Create contents of the button bar.
	 * @param parent
	 */
	@Override
	protected void createButtonsForButtonBar(Composite parent) {
		_button = createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
		_button.setText("Close");
		_button.setEnabled(true);
	}

	/**
	 * Return the initial size of the dialog.
	 */
	@Override
	protected Point getInitialSize() {
		return new Point(551, 227);
	}
	
	

	

	

	
	
	
	
	
	
	
	
	
	
	
	
	
	public void initDataDrawable(){
		
		//TODO Drawable
		System.out.println("> Placement Manager init:");
		
		_btnRun.setEnabled(false);
		_bar.setSelection(45);
		
		loadObjects();
		_bar.setSelection(65);
		solve();
		_bar.setSelection(80);

		repaint();
		_bar.setSelection(100);
		
		_button.setEnabled(true);

	}
	
	
	private void solve(){
		
		for(ObjectModel o : _olist){					
			o.normalize();
			
			Point max = o.getMaxCoord();
			
			int countX = _size.x - max.x;
			int countY = _size.y - max.y;
			

			boolean next = false;
			
			
			for(int i = 0; i <= countY; i++){						// Y Axis
				o.move(0, i);
				

				for(int j = 0; j <= countX; j++){					//X Axis
					
					o.move(1, 0);
					
					if (allPointsInDomain(o)){
						if (!otherIntersection(o)){
								
							if (aniMatch(o)){
								System.err.println("KAWAPANGA! " + i + "     " + j);
								next = true;
								break;
							}	
						}
					}	
				}
				if(!next)
					o.normalize();
				else{
					_placedlist.add(o);
					break;
				}
			}
		}

		
	}
	
	

	
	
	private boolean aniMatch(ObjectModel o){
		Point op = o.getRandomAniPoint();
		
		for(Point p : _ani.getPointsList()){
			if(op.equals(p))
				return true;
		}
		
		return false;
	}
	
	private boolean otherIntersection(ObjectModel o){
		for(ObjectModel ooo : _placedlist){
			if (!ooo.equals(o) && intersect(ooo, o))
				return true;
		}
		return false;
	}
	
	private boolean intersect(ObjectModel o1, ObjectModel o2){
		Polygon r1 = o1.getPolygon();
		Polygon r2 = o2.getPolygon();
		
		for(Point p : o1.getShellPoints()){
			if(r2.contains(new java.awt.Point(p.x, p.y)))
				return true;
		}
		
		for(Point p : o2.getShellPoints()){
			if(r1.contains(new java.awt.Point(p.x, p.y)))
				return true;
		}
		
//		r1.dispose();
//		r2.dispose();
//		o1.disposeRegion();
//		o2.disposeRegion();
		
		return false;
	}
	
	private boolean allPointsInDomain(ObjectModel o){
		for(Point p : o.getShellPoints()){
			if(!_domain.contains(p))
				return false;
		}
		return true;
	}
	
	
	private void repaint(){
		_drawArea.getDrawAreaComposite().addPaintListener(new PaintListener() {
			public void paintControl(PaintEvent e) {
				
				
				for(ObjectModel o : _placedlist){
					o.paint(e.gc);
				}
			}
		});
		
		_drawArea.getDrawAreaComposite().redraw();
	}
	
	
	private void loadObjects(){
		_olist.clear();
		
		File dir0 = new File(_ani.getAniModel().getAniPath()).getParentFile().getParentFile();
		File dir = new File(dir0.getPath() + "//Objects");
		
		FileFilter ff = new FileFilter(){

			@Override
			public boolean accept(File f) {
				if (f.getPath().toLowerCase().endsWith("jade"))
					return true;
				return false;
			}
			
		};
		
//		work(2);
		
		for(File f : dir.listFiles(ff)){
			ObjectModel m = new ObjectModel(f.getPath());
			if(m.getLoadStatus() == ObjectModel.LOAD_OK){
				
				if (m.hasAni() && m.checkAni(_aniName)){
					m.normalize();
					_olist.add(m);
					
				}
				
			}
		}
		
//		work(3);
		
		System.out.println("> " + _olist.size() + " objects loaded");
	}
	
	
	
	
	
	
	
	
	
	
	//-----------------PlugablePlugablePlugable
	//-----------------Plugable			Plugable
	//-----------------Plugable			Plugable
	//-----------------Plugable			Plugable
	//-----------------Plugable			Plugable
	//-----------------PlugablePlugablePlugable
	//-----------------Plugable
	//-----------------Plugable
	//-----------------Plugable
	//-----------------Plugable
	//-----------------Plugable
	
	
	
	
	
	private void initDataPlugable(){
		//TODO
		
		_btnRun.setEnabled(false);
		_bar.setSelection(45);
		
		loadAllObjects();
		
		_plugAni.setObjectList(_olist);
		
		int[] x = {_drawArea.getDrawAreaSize().x};
		int[] y = {_drawArea.getDrawAreaSize().y};
		_plugAni.setDomain(new Polygon(x, y, x.length));
		
		_placedlist = _plugAni.solve();
		_bar.setSelection(90);
		repaint();
		_bar.setSelection(100);
		_button.setEnabled(true);
	}
	
	private void loadAllObjects(){
		_olist.clear();
		
		File dir0 = _pathFile.getParentFile().getParentFile();
		//File dir0 = new File(_ani.getAniModel().getAniPath()).getParentFile().getParentFile();
		File dir = new File(dir0.getPath() + "//Objects");
		
		FileFilter ff = new FileFilter(){

			@Override
			public boolean accept(File f) {
				if (f.getPath().toLowerCase().endsWith("jade"))
					return true;
				return false;
			}
			
		};
		
//		work(2);
		
		for(File f : dir.listFiles(ff)){
			ObjectModel m = new ObjectModel(f.getPath());
			if(m.getLoadStatus() == ObjectModel.LOAD_OK){	
				_olist.add(m);
			}
		}
		
//		work(3);
		
		System.out.println("> " + _olist.size() + " objects loaded");
	}
	
	
	
	
	
	
}
